<?php
namespace StarCloud\Models;

use Phalcon\Db\Column;
use StarCloud\Library\Exception;

trait BalanceBase
{
    public function getTableName()
    {
        return $this->tableName;
    }

    /**
     * @return self
     */
    public static function txIncr($uid, $amount)
    {
        if (($record = static::findFirstByUidForUpdate($uid)) == false) {
            throw new Exception('10001');
        }
        $record->incr($amount);

        return $record;
    }

    /**
     * @return self
     */
    public static function txDecr($uid, $amount)
    {
        if (($record = static::findFirstByUidForUpdate($uid)) == false) {
            throw new Exception('10001');
        }
        $record->decr($amount);

        return $record;
    }

    /**
     * @return self
     */
    public static function getRecord($uid)
    {
        if (($record = static::findFirstByUidForUpdate($uid)) == false) {
            $record = static::newRecord($uid);
        }

        return $record;
    }

    public static function newRecord($uid)
    {
        $record = new static();
        $record->uid = $uid;
        $record->balance = 0;
        $record->locked_amount = 0;
        $record->save();

        return $record;
    }

    public function incr(int $amount)
    {
        $this->balance = $this->balance + $amount;
        $this->save();
    }

    public function decr(int $amount)
    {
        // 降低的时候必须考虑锁定的金额
        if ($this->getBalance() < $amount) {
            throw new Exception('10001');
        }

        $this->balance = $this->balance - $amount;
        $this->save();
    }

    public function getBalance()
    {
        return (int) $this->balance;
    }

    public static function findFirstByUidForUpdate($uid)
    {
        return self::findFirst([
            'conditions' => 'uid = :uid:',
            'bind' => ['uid' => $uid],
            'bindTypes' => ['uid' => Column::BIND_PARAM_INT],
            'for_update' => true,
        ]);
    }

    // 表的字段
    protected $id;
    protected $uid;
    protected $balance;
    protected $locked_amount;
    protected $created_time;
    protected $updated_time;
}
